package miggy.dma;

import miggy.SystemModel;
import miggy.api.cpu.Size;
import miggy.api.memory.CustomRegisterObserver;
import miggy.utils.TextUtil;
import miggy.memory.CustomRegisters;

/*
//  Miggy - Java Amiga MachineCore
//  Copyright (c) 2008, Tony Headford
//  All rights reserved.
//
//  Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
//  following conditions are met:
//
//    o  Redistributions of source code must retain the above copyright notice, this list of conditions and the
//       following disclaimer.
//    o  Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
//       following disclaimer in the documentation and/or other materials provided with the distribution.
//    o  Neither the name of the Miggy Project nor the names of its contributors may be used to endorse or promote
//       products derived from this software without specific prior written permission.
//
//  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
//  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
//  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
//  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
//  SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
//  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
//  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// $Revision: 21 $
*/

public class BitplaneChannel extends BaseDMAChannel
{
	private int wndStart;
	private int wndSop;
	private int dataStart;
	private int dataStop;
	private boolean hires;
	private boolean ham;
	private int bplanes;
	private boolean dualPlayfield;
	private boolean lace;
	private int bpl1mod;
	private int bpl2mod;
	private int bpl1pth;
	private int bpl2pth;
	private int bpl3pth;
	private int bpl4pth;
	private int bpl5pth;
	private int bpl6pth;

	public BitplaneChannel()
	{
		super("Bitplane DMA Channel");
		reset();
		addObservers();
	}

	private void addObservers()
	{
		SystemModel.REGS.addObserver(CustomRegisters.BPLCON0, new CustomRegisterObserver() {
			public void update(int register, int value, Size size)
			{
				hires = (value & 0x8000) != 0;
				bplanes = (value & 0x7000) >> 12;
				ham = (value & 0x0800) != 0;
				dualPlayfield = (value & 0x0400) != 0;
				lace = (value & 0x0004) != 0;
				dataStart = value;
				logger.info("BPLCON0: " + TextUtil.toHex((short)value));
			}
		});

		SystemModel.REGS.addObserver(CustomRegisters.DDFSTRT, new CustomRegisterObserver() {
			public void update(int register, int value, Size size)
			{
				dataStart = value;
				logger.info("DDFSTRT: " + TextUtil.toHex((short)value));
			}
		});

		SystemModel.REGS.addObserver(CustomRegisters.DDFSTOP, new CustomRegisterObserver() {
			public void update(int register, int value, Size size)
			{
				dataStop = value;
				logger.info("DDFSTOP: " + TextUtil.toHex((short)value));
			}
		});

		SystemModel.REGS.addObserver(CustomRegisters.BPL1PTH, new CustomRegisterObserver() {
			public void update(int register, int value, Size size)
			{
				if(size == Size.Word)
				{
					bpl1pth &= 0x000ffff;
					bpl1pth |= (value << 16);
				}
				else
				{
					bpl1pth = value;
				}

				logger.info("BPL1PTH: " + TextUtil.toHex((short)value));
			}
		});

		SystemModel.REGS.addObserver(CustomRegisters.BPL2PTH, new CustomRegisterObserver() {
			public void update(int register, int value, Size size)
			{
				if(size == Size.Word)
				{
					bpl2pth &= 0x000ffff;
					bpl2pth |= (value << 16);
				}
				else
				{
					bpl2pth = value;
				}

				logger.info("BPL2PTH: " + TextUtil.toHex((short)value));
			}
		});

		SystemModel.REGS.addObserver(CustomRegisters.BPL3PTH, new CustomRegisterObserver() {
			public void update(int register, int value, Size size)
			{
				if(size == Size.Word)
				{
					bpl3pth &= 0x000ffff;
					bpl3pth |= (value << 16);
				}
				else
				{
					bpl3pth = value;
				}

				logger.info("BPL3PTH: " + TextUtil.toHex((short)value));
			}
		});

		SystemModel.REGS.addObserver(CustomRegisters.BPL4PTH, new CustomRegisterObserver() {
			public void update(int register, int value, Size size)
			{
				if(size == Size.Word)
				{
					bpl4pth &= 0x000ffff;
					bpl4pth |= (value << 16);
				}
				else
				{
					bpl4pth = value;
				}

				logger.info("BPL4PTH: " + TextUtil.toHex((short)value));
			}
		});

		SystemModel.REGS.addObserver(CustomRegisters.BPL5PTH, new CustomRegisterObserver() {
			public void update(int register, int value, Size size)
			{
				if(size == Size.Word)
				{
					bpl5pth &= 0x000ffff;
					bpl5pth |= (value << 16);
				}
				else
				{
					bpl5pth = value;
				}

				logger.info("BPL5PTH: " + TextUtil.toHex((short)value));
			}
		});

		SystemModel.REGS.addObserver(CustomRegisters.BPL6PTH, new CustomRegisterObserver() {
			public void update(int register, int value, Size size)
			{
				if(size == Size.Word)
				{
					bpl6pth &= 0x000ffff;
					bpl6pth |= (value << 16);
				}
				else
				{
					bpl6pth = value;
				}

				logger.info("BPL6PTH: " + TextUtil.toHex((short)value));
			}
		});

		SystemModel.REGS.addObserver(CustomRegisters.BPL1MOD, new CustomRegisterObserver() {
			public void update(int register, int value, Size size)
			{
				bpl1mod = value;
				logger.info("BPL1MOD: " + TextUtil.toHex((short)value));
			}
		});

		SystemModel.REGS.addObserver(CustomRegisters.BPL2MOD, new CustomRegisterObserver() {
			public void update(int register, int value, Size size)
			{
				bpl2mod = value;
				logger.info("BPL2MOD: " + TextUtil.toHex((short)value));
			}
		});
	}

	public void reset()
	{
		enabled = false;
		hires = false;
		lace = false;
		dualPlayfield = false;
		ham = false;
		bplanes = 0;

		bpl1pth = 0;
		bpl2pth = 0;
		bpl3pth = 0;
		bpl4pth = 0;
		bpl5pth = 0;
		bpl6pth = 0;

		bpl1mod = 0;
		bpl2mod = 0;
	}


	public int doWork(int scanline)
	{
		//build data for scanline
		//need to convert planar data to chunky
		//store pixels in the indexbuffer as these values are not RGB but a colour register identifier
		//and these can be changed by the copper
//		if(scanline < vstart || scanline > vstop)
//			return 0;

		return 0;
	}
}
